#ifndef YHAIDA_EVENTLOOP_H
#define YHAIDA_EVENTLOOP_H
#include "../base/Utils.h"
#include "../logging/Logging.h"
#include "../mutex/MutexLock.h"
#include "Callbacks.h"
#include "TimeId.h"
#include <stdio.h>
#include <poll.h>
#include <cassert>
#include <memory>
#include <vector>
#include <sys/eventfd.h>
#include <functional>
namespace yhaida
{
    //前向声明
    class Channel;
    // class Poller;
    class EPoller;

    class TimerQueue;

    class EventLoop : Utils::nocapyable
    {
    public:
        typedef std::vector<Channel *> ChannelList;
        typedef std::function<void()> Functor;
        typedef std::function<void()> TimerCallback;

    public:
        EventLoop();
        ~EventLoop();
        //运行
        void loop();
        void quit();

        Timestamp pollReturnTime() { return _pollReturnTime; }

        //在其他非IO线程调用的函数可以转移到IO线程来调用void doPendingFunctors();
        void runInLoop(const Functor &cb);
        void queueInLoop(const Functor &cb);
        void wakeup();

        TimerID runAt(const Timestamp &time, const TimerCallback &cb);
        TimerID runAfter(double delay, const TimerCallback &cb);
        TimerID runEvery(double interval, const TimerCallback &cb);

        void cancel(TimerID timerId);

        // assert()
        void assertInLoopThread();
        //判断
        bool isInLoopThread();

        static EventLoop *getEventLoopOfCurrentThread();

    public:
        void ChannelUpDate(Channel *channel);
        void removeChannel(Channel *channel);

    private:
        //异常
        void abortNotInLoopThread();
        void handleRead();
        void doPendingFunctors();

        bool _looping;
        bool _quit;

        bool _callingPendingFunctors;

        //一个EventLoop唯一
        const pid_t _EventLoopThreadID;
        Timestamp _pollReturnTime;

        // std::unique_ptr<Poller> _poller;
        std::unique_ptr<EPoller> _poller;
        std::unique_ptr<TimerQueue> _timerQueue;

        int _wakeupFd;
        std::unique_ptr<Channel> _wakeupChannel;
        ChannelList _EventLoopActiveChannels;

        MutexLock _wakeupMutex;
        std::vector<Functor> _pendingFunctors;
    };

}

#endif